package cn.lili.controller.pay.pufa;

import cn.hutool.core.lang.UUID;
import cn.lili.modules.bank.entity.dos.DockingBankVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@RestController
@RequestMapping("/manager/pay")
@Transactional(rollbackFor = Exception.class)
@Validated
public class PuFaPayController {
	// 加密
	private static String contentType = "INFOSEC_SIGN/1.0";
	// 解密
	private static String contentType2 = "INFOSEC_VERIFY_SIGN/1.0";
	// 加密与解密接口
	private static String url = "http://47.93.60.120:4437";
	// 请求报文接口
	private static String url2 = "http://47.93.60.120:6777";
	// 甲方浦发银行账号
	private static String paymentAccount = "65140078801800000315";
	// 甲方浦发银行用户名
	private static String paymentAccountName = "黑龙江融商易联网络信息科技有限公司";
	// 甲方浦发银行开户号
	private static String beneficiaryBank = "2024218618";
	// 单号
	private static String danhao = "";

	/**
	 * 浦发银行发起转账
	 *
	 * @param dockingBankVO
	 * @return
	 * @throws IOException
	 */
	public static int puFaWithdrawal(DockingBankVO dockingBankVO) throws IOException {
		danhao = getShortUuid();
		// 生成<body>中的数据
		String sign = getSign(dockingBankVO);
		log.info("8001body内容: {}", sign);
		// <body>加密签名
		String send = send(sign, contentType, url);
		// 合成报文整体
		log.info("8001body内容-加密: {}", send);
		// 完整串
		String complete = "<?xml version='1.0' encoding='GB2312'?><packet><head><transCode>8801</transCode><signFlag>1</signFlag><masterID>"
				+ beneficiaryBank + "</masterID><packetID>" + UUID.fastUUID() + "</packetID><timeStamp>" + getDateTime()
				+ "</timeStamp></head><body><signature>content</signature></body></packet>";
		// 获取加密内容
		String contentSign = getContentSign(send);
		// 替换内容
		String content2 = complete.replace("content", contentSign);
		log.info("8001body内容-加密-发送: {}", content2);
		// 走银行接口进行转账
		String xmlContents = sendPost(content2, url2);
		log.info("8001body内容-加密-发送-返回: {}", xmlContents);
		String contentReturnSignature = "";
		try {
			contentReturnSignature = getContentReturnSignature(xmlContents);
		} catch (Exception e) {
			return 1;
		}
		String send1 = sendJiemi(contentReturnSignature, contentType2, url);
		log.info("8801报文解密内容: {}", send1);
		String transStatus = getTransStatus(send1);
		// 0转账成功 转账成功获取转账结果状态
		if ("4".equals(transStatus)) {
			return 0;
		} else {
			// 转账失败
			return 1;
		}
	}

	/**
	 * 加密信息
	 *
	 * @param dockingBankVO
	 * @return
	 */
	public static String getSign(DockingBankVO dockingBankVO) {
		// 判断是本行还是他行
		String sysFlag = dockingBankVO.getPayeeBankName().contains("浦发银行") ? "0" : "1";
		// 合成xml 初始化
		String body = "<body>" + "<elecChequeNo>" + danhao + "</elecChequeNo>" + "<acctNo>付款账号</acctNo>"
				+ "<acctName>付款人账户名称</acctName>" + "<payeeAcctNo>收款人账号</payeeAcctNo>" + "<payeeName>收款人名称</payeeName>"
				+ "<amount>支付金额</amount>" + "<sysFlag>同行/它行</sysFlag>" + "<remitLocation>1</remitLocation>"
				+ "<remitPurpose>P</remitPurpose>" + "<payeeBankNo>收款行行号</payeeBankNo>"
				+ "<payeeBankSelectFlag>1</payeeBankSelectFlag>" + "</body>";

		// a. 同城本行 打款正常 0 0
		// b. 同城他行 打款正常 0 1
		// c. 异地他行 打款正常 1 1 1
		// d. 异地本行 未测试 1 0 1
		String replace = body.replace("付款账号", paymentAccount).replace("付款人账户名称", paymentAccountName)
				.replace("收款人账号", dockingBankVO.getPayeeAcctNo()).replace("收款人名称", dockingBankVO.getPayeeName())
				.replace("支付金额", String.valueOf(dockingBankVO.getAmount())).replace("同行/它行", (sysFlag))
				.replace("收款行行号", dockingBankVO.getBankCode());
		return replace;
	}

	/**
	 * 进行加密
	 *
	 * @param content
	 * @param contentType
	 * @param url
	 * @return
	 * @throws IOException
	 */
	public static String send(String content, String contentType, String url) throws IOException {
		// 转换content内容
		byte[] bytes = StringToByte(content);
		URL urll = new URL(url);
		HttpURLConnection con1 = (HttpURLConnection) urll.openConnection();
		con1.setDoInput(true);
		con1.setDoOutput(true);
		con1.setRequestMethod("POST");
		con1.setRequestProperty("Content-Type", contentType);
		con1.connect();
		con1.getOutputStream().write(bytes);
		con1.getOutputStream().flush();
		InputStream in = con1.getInputStream();
		byte[] respBytes = toByteArray(in);
		String result = new String(respBytes, "gb2312");
		return result;
	}

	/**
	 * 发送报文
	 *
	 * @param content
	 * @param url
	 * @return
	 * @throws IOException
	 */
	public static String sendPost(String content, String url) throws IOException {
		String xmlContent = "00" + (content.length() + 6) + content;
		byte[] bytes = StringToByte(xmlContent);
		URL urll = new URL(url);
		HttpURLConnection con1 = (HttpURLConnection) urll.openConnection();
		con1.setDoInput(true);
		con1.setDoOutput(true);
		con1.setRequestMethod("POST");
		con1.setRequestProperty("Content-Length", "00" + (content.length() + 6));
		con1.connect();
		con1.getOutputStream().write(bytes);
		con1.getOutputStream().flush();
		InputStream in = con1.getInputStream();
		byte[] respBytes = toByteArray(in);
		String result = new String(respBytes);
		return result;
	}

	/**
	 * String转byte
	 *
	 * @param content
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] StringToByte(String content) throws UnsupportedEncodingException {
		byte[] gbks = new String(content.getBytes("GBK"), "GBK").getBytes("GBK");
		return gbks;
	}

	/**
	 * 流转String
	 *
	 * @param inputStream
	 * @return
	 */
	public static String getStringByInputStream(InputStream inputStream) {
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		try {
			byte[] b = new byte[10240];
			int n;
			while ((n = inputStream.read(b)) != -1) {
				outputStream.write(b, 0, n);
			}
		} catch (Exception e) {
			try {
				inputStream.close();
				outputStream.close();
			} catch (Exception e1) {
			}
		}
		return outputStream.toString();
	}

	/**
	 * 获取send内容 sign
	 *
	 * @param aa
	 * @return
	 */
	public static String getContentSign(String aa) {
		String str = aa.substring(0, aa.indexOf("<sign>"));
		String bb = aa.substring(str.length() + 6, aa.length());
		String str1 = bb.substring(0, bb.indexOf("</sign>"));
		return str1;
	}

	/**
	 * 获取send内容 transStatus
	 *
	 * @param aa
	 * @return
	 */
	public static String getTransStatus(String aa) {
		String str = aa.substring(0, aa.indexOf("<transStatus>"));
		String bb = aa.substring(str.length() + 13, aa.length());
		String str1 = bb.substring(0, bb.indexOf("</transStatus>"));
		return str1;
	}

	/**
	 * 获取send内容 returnCode
	 *
	 * @param aa
	 * @return
	 */
	public static String getContentReturnSignature(String aa) {
		String str = aa.substring(0, aa.indexOf("<signature>"));
		String bb = aa.substring(str.length() + 11, aa.length());
		String str1 = bb.substring(0, bb.indexOf("</signature>"));
		return str1;
	}

	/**
	 * 获取年月日时分秒
	 *
	 * @return
	 */
	public static String getDateTime() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sdf.format(new Date());
	}

	/**
	 * 去掉String换行符
	 *
	 * @param str
	 * @return
	 */
	public static String replaceAllBlank(String str) {
		String s = "";
		if (str != null) {
			Pattern p = Pattern.compile("\\s*|\t|\r|\n");
			/**
			 * \n 回车(\u000a) \t 水平制表符(\u0009) \s 空格(\u0008) 去掉了 "\\s*|\t|r|\n" \r 换行(\u000d)
			 */
			Matcher m = p.matcher(str);
			s = m.replaceAll("");
		}
		return s;
	}

	/**
	 * 随机数组
	 */
	public static String[] chars = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
			"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8",
			"9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
			"U", "V", "W", "X", "Y", "Z"};

	/**
	 * 获取随机数
	 *
	 * @return
	 */
	public static String getShortUuid() {
		StringBuffer shortBuffer = new StringBuffer();
		String uuid = UUID.randomUUID().toString().replace("-", "");
		for (int i = 0; i < 8; i++) {
			String str = uuid.substring(i * 4, i * 4 + 4);
			int x = Integer.parseInt(str, 16);
			shortBuffer.append(chars[x % 0x3E]);
		}
		return shortBuffer.toString();
	}

	/**
	 * 进行解密
	 *
	 * @param content
	 * @param contentType
	 * @param url
	 * @return
	 * @throws IOException
	 */
	public static String sendJiemi(String content, String contentType, String url) throws IOException {
		// 转换content内容
		byte[] bytes = StringToByte(content);
		URL urll = new URL(url);
		HttpURLConnection con1 = (HttpURLConnection) urll.openConnection();
		con1.setDoInput(true);
		con1.setDoOutput(true);
		con1.setRequestMethod("POST");
		con1.setRequestProperty("Content-Length", String.valueOf(content.length()));
		con1.setRequestProperty("Content-Type", contentType);
		con1.connect();
		con1.getOutputStream().write(bytes);
		con1.getOutputStream().flush();
		InputStream in = con1.getInputStream();
		byte[] respBytes = toByteArray(in);
		String result = new String(respBytes);
		return result;
	}

	/**
	 * 转数组
	 *
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private static byte[] toByteArray(InputStream is) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			byte[] b = new byte[4096];
			boolean var3 = false;
			int n;
			while ((n = is.read(b)) != -1) {
				output.write(b, 0, n);
			}
			byte[] var4 = output.toByteArray();
			return var4;
		} finally {
			output.close();
		}
	}

}
